{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Deep Neural Network in TensorFlow"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this notebook, we convert our [intermediate-depth MNIST-classifying neural network](https://github.com/the-deep-learners/TensorFlow-LiveLessons/blob/master/notebooks/intermediate_net_in_keras.ipynb) from Keras to TensorFlow (compare them side by side) following Aymeric Damien's [Multi-Layer Perceptron Notebook](https://github.com/aymericdamien/TensorFlow-Examples/blob/master/notebooks/3_NeuralNetworks/multilayer_perceptron.ipynb) style. \n",
    "\n",
    "Subsequently, we add a layer to make it deep! "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Load dependencies"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "np.random.seed(42)\n",
    "import tensorflow as tf\n",
    "tf.set_random_seed(42)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Load data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from tensorflow.examples.tutorials.mnist import input_data\n",
    "mnist = input_data.read_data_sets(\"MNIST_data/\", one_hot=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Set neural network hyperparameters (tidier at top of file!)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "lr = 0.1\n",
    "epochs = 1\n",
    "batch_size = 128\n",
    "weight_initializer = tf.contrib.layers.xavier_initializer()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Set number of neurons for each layer"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "n_input = 784\n",
    "n_dense_1 = 64\n",
    "n_dense_2 = 64\n",
    "n_classes = 10"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Define placeholders Tensors for inputs and labels"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "x = tf.placeholder(tf.float32, [None, n_input])\n",
    "y = tf.placeholder(tf.float32, [None, n_classes])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Define types of layers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# dense layer with ReLU activation:\n",
    "def dense(x, W, b):\n",
    "    # DEFINE\n",
    "    # DEFINE\n",
    "    return a"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Define dictionaries for storing weights and biases for each layer -- and initialize"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "bias_dict = {\n",
    "    'b1': tf.Variable(tf.zeros([n_dense_1])), \n",
    "    'b2': tf.Variable(tf.zeros([n_dense_2])),\n",
    "    'b_out': tf.Variable(tf.zeros([n_classes]))\n",
    "}\n",
    "\n",
    "weight_dict = {\n",
    "    'W1': tf.get_variable('W1', [n_input, n_dense_1], initializer=weight_initializer),\n",
    "    'W2': tf.get_variable('W2', [n_dense_1, n_dense_2], initializer=weight_initializer),\n",
    "    'W_out': tf.get_variable('W_out', [n_dense_2, n_classes], initializer=weight_initializer)\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Design neural network architecture"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def network(x, weights, biases):\n",
    "    \n",
    "    # DEFINE\n",
    "  \n",
    "    return out_layer_z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Build model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "predictions = network(x, weights=weight_dict, biases=bias_dict)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Define model's loss and its optimizer"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=predictions, labels=y))\n",
    "optimizer = tf.train.GradientDescentOptimizer(learning_rate=lr).minimize(cost)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Define evaluation metrics"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# calculate accuracy by identifying test cases where the model's highest-probability class matches the true y label: \n",
    "correct_prediction = tf.equal(tf.argmax(predictions, 1), tf.argmax(y, 1))\n",
    "accuracy_pct = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) * 100"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Create op for variable initialization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "initializer_op = tf.global_variables_initializer()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Train the network in a session"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "with tf.Session() as session:\n",
    "    session.run(initializer_op)\n",
    "    \n",
    "    print(\"Training for\", epochs, \"epochs.\")\n",
    "    \n",
    "    # loop over epochs: \n",
    "    for epoch in range(epochs):\n",
    "        \n",
    "        avg_cost = 0.0 # track cost to monitor performance during training\n",
    "        avg_accuracy_pct = 0.0\n",
    "        \n",
    "        # loop over all batches of the epoch:\n",
    "        n_batches = int(mnist.train.num_examples / batch_size)\n",
    "        for i in range(n_batches):\n",
    "            \n",
    "            batch_x, batch_y = mnist.train.next_batch(batch_size)\n",
    "            \n",
    "            # feed batch data to run optimization and fetching cost and accuracy: \n",
    "            _, batch_cost, batch_acc = session.run([optimizer, cost, accuracy_pct], \n",
    "                                                   feed_dict={x: batch_x, y: batch_y})\n",
    "            \n",
    "            # accumulate mean loss and accuracy over epoch: \n",
    "            avg_cost += batch_cost / n_batches\n",
    "            avg_accuracy_pct += batch_acc / n_batches\n",
    "            \n",
    "        # output logs at end of each epoch of training:\n",
    "        print(\"Epoch \", '%03d' % (epoch+1), \n",
    "              \": cost = \", '{:.3f}'.format(avg_cost), \n",
    "              \", accuracy = \", '{:.2f}'.format(avg_accuracy_pct), \"%\", \n",
    "              sep='')\n",
    "    \n",
    "    print(\"Training Complete. Testing Model.\\n\")\n",
    "    \n",
    "    test_cost = cost.eval({x: mnist.test.images, y: mnist.test.labels})\n",
    "    test_accuracy_pct = accuracy_pct.eval({x: mnist.test.images, y: mnist.test.labels})\n",
    "    \n",
    "    print(\"Test Cost:\", '{:.3f}'.format(test_cost))\n",
    "    print(\"Test Accuracy: \", '{:.2f}'.format(test_accuracy_pct), \"%\", sep='')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
